package vsvm.gui.objects;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.JFileChooser;

import vsvm.classifier.AbstractClassifier;
import vsvm.classifier.AbstractTestSet;
import vsvm.data.filter.AbstractFilter;
import vsvm.data.model.AbstractDataModel;
import vsvm.data.source.AbstractDataSource;
import vsvm.gui.Environment;
import vsvm.gui.events.WorkspaceChangedListener;

public class Workspace implements Serializable {
	
	private static final long serialVersionUID = 100L;
	
	private ArrayList<AbstractDataSource> dataSources;
	private ArrayList<AbstractDataModel> dataModels;
	private ArrayList<AbstractFilter> filters;
	private ArrayList<AbstractClassifier> classifiers;
	private ArrayList<AbstractTestSet> testSets;
	private ArrayList<WorkspaceChangedListener> changeListeners;
	
	private String savePath = null;
	
	public Workspace() {
		dataSources = new ArrayList<AbstractDataSource>();
		dataModels = new ArrayList<AbstractDataModel> ();
		filters = new ArrayList<AbstractFilter> ();
		classifiers = new ArrayList<AbstractClassifier> ();
		changeListeners =  new ArrayList<WorkspaceChangedListener>();
		
		testSets = new ArrayList<AbstractTestSet>();
	}
	
	public ArrayList<AbstractDataSource> getDataSources() {
		return dataSources;
	}
	
	public void addDataSource(AbstractDataSource dataSource) {
		dataSources.add(dataSource);
		fireChangedEvent();
	}
	
	public void deleteDataSource(AbstractDataSource dataSource) {
		dataSources.remove(dataSource);
		fireChangedEvent();
	}
	
	public ArrayList<AbstractDataModel> getDataModels() {
		return dataModels;
	}
	
	public void addDataModel(AbstractDataModel dataModel) {
		dataModels.add(dataModel);
		fireChangedEvent();
	}
	
	public void deleteDataModel(AbstractDataModel dataModel) {
		dataModels.remove(dataModel);
		fireChangedEvent();
	}
	
	public ArrayList<AbstractFilter> getFilters() {
		return filters;
	}
	
	public void addFilter(AbstractFilter filter) {
		filters.add(filter);
		fireChangedEvent();
	}
	
	public void deleteFilter(AbstractFilter filter) {
		filters.remove(filter);
		fireChangedEvent();
	}
	
	
	public ArrayList<AbstractClassifier> getClassifiers() {
		return classifiers;		
	}
		
	public void addClassifier(AbstractClassifier cls) {
		classifiers.add(cls);
		fireChangedEvent();
	}
	
	public void deleteClassifier(AbstractClassifier cls) {
		classifiers.remove(cls);
		fireChangedEvent();
	}
	
	
	public ArrayList<AbstractTestSet> getTestSets() {
		return testSets;
	}
	
	public void addTestSet(AbstractTestSet test) {
		testSets.add(test);
		fireChangedEvent();
	}
	
	public void deleteTestSet(AbstractTestSet test) {
		testSets.remove(test);
		fireChangedEvent();
	}
	
	
	
	public void addChangeListener(WorkspaceChangedListener listener) {
		if (!changeListeners.contains(listener))
			changeListeners.add(listener);
	}

	
	private void fireChangedEvent() {
		for (Iterator<WorkspaceChangedListener> iter = changeListeners.iterator(); iter.hasNext();) {
			iter.next().workspaceChanged();			
		}		
	}
	
		
	public void save() {
		if (savePath == null) {
			JFileChooser fc = new JFileChooser();
			int opt = fc.showSaveDialog(Environment.getEnvironment().getMainFrame());
			if (opt != JFileChooser.APPROVE_OPTION) return;
			savePath = fc.getSelectedFile().getPath();			
		}
		
		try {
			FileOutputStream out = new FileOutputStream(savePath);
			ObjectOutputStream s = new ObjectOutputStream(out);
			s.writeObject(this);
			s.flush();
		} catch (Exception x) {
			x.printStackTrace();
		}		
	}
	
	public void setSaveFilePath(String path) {
		savePath = path;
	}	
	
    private void writeObject(ObjectOutputStream out) throws IOException {
		out.writeObject(dataSources);
		out.writeObject(dataModels);
		out.writeObject(filters);
		out.writeObject(classifiers);
		out.writeObject(testSets);
	}

	private void readObject(ObjectInputStream in) throws IOException,
			ClassNotFoundException {
		dataSources = (ArrayList<AbstractDataSource>)in.readObject();
		dataModels = (ArrayList<AbstractDataModel>)in.readObject();
		filters = (ArrayList<AbstractFilter>)in.readObject();
		classifiers = (ArrayList<AbstractClassifier>)in.readObject();
		changeListeners = new ArrayList<WorkspaceChangedListener>();
		//testSets = new ArrayList<AbstractTestSet>();
		testSets = (ArrayList<AbstractTestSet>)in.readObject();
	}

	public static Workspace loadFromFile(String path) {
		try {
		  FileInputStream in = new FileInputStream(path);
	      ObjectInputStream ois = new ObjectInputStream(in);
	      Workspace wsp = (Workspace)ois.readObject();
	      wsp.savePath = path;
	      
	      return wsp;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

}
